﻿using System.Threading.Tasks;
using IceDog.DNC.Program.WebApi.Repositories;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;

namespace IceDog.DNC.Program.WebApi.CustomMiddleware
{
    public static class SetHeaderTagsMiddlewareExtensions
    {
        /// <summary>
        /// 给头添加标签
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseSetHeaderTags(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<SetHeaderTagsMiddleware>();
        }

        /// <summary>
        /// 给头添加标签
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="identity"></param>
        /// <param name="useFor"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseSetHeaderTags(this IApplicationBuilder builder, string identity, string useFor)
        {
            return builder.UseMiddleware<SetHeaderTagsMiddleware>(identity,useFor);
        }

        /// <summary>
        /// 给头添加标签
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseSetHeaderTags(this IApplicationBuilder builder,params object[] args)
        {
            return builder.UseMiddleware<SetHeaderTagsMiddleware>(args);
        }
    }
    public class SetHeaderTagsMiddleware
    {
        private readonly RequestDelegate _next;
        private string _identity;
        private string _useFor;
        private IStringRepository _stringRepository;

        //UseMiddleware会根据构造函数参数进行匹配最佳构造函数
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="next"></param>
        public SetHeaderTagsMiddleware(RequestDelegate next)
        {
            _next = next;
            _identity = "IceDog";
            _useFor = "Test";
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="next">下构造函数参数中的RequestDelegate参数不是必须放在第一个，
        /// 可以是任意位置，这里仅测试用(实践证明，现在的版本是必须放在第一个了)</param>
        /// <param name="identity"></param>
        /// <param name="useFor"></param>
        public SetHeaderTagsMiddleware(RequestDelegate next,string identity, string useFor) :this(next)
        {
            _identity = identity;
            _useFor = useFor;
        }

        /// <summary>
        ///  just for test
        /// </summary>
        /// <param name="next"></param>
        /// <param name="identity"></param>
        /// <param name="useFor"></param>
        /// <param name="name"></param>
        /// <param name="num">有默认值可以匹配构造函数的时候让app.UseSetHeaderTags("a ton of params", "test.", "any")匹配到</param>
        public SetHeaderTagsMiddleware(RequestDelegate next, string identity, string useFor,string name,int num=1) : this(next)
        {
            _identity = identity;
            _useFor = useFor;
        }

        /// <summary>
        /// just for test
        /// </summary>
        /// <param name="next"></param>
        /// <param name="useString">
        /// 如果没有此参数调用app.UseSetHeaderTags()，按照匹配构造函数约定，则通过匹配参数就不会使用此构造函数，
        /// 而是使用构造函数参数为(RequestDelegate next)那一个
        /// app.UseSetHeaderTags(true)可以匹配到此构造函数，
        /// 如果useString有默认值，调用app.UseSetHeaderTags()仍然不会调用此构造函数，除非构造函数参数为(RequestDelegate next)的构造函数
        /// 不存在（注释掉），才会调用此构造函数。
        /// </param>
        /// <param name="stringRepository">通过容器注入</param>
        public SetHeaderTagsMiddleware(RequestDelegate next, bool useString,IStringRepository stringRepository) : this(next)
        {
            _next = next;
            _stringRepository = stringRepository;
        }

        /// <summary>
        /// 约定方法，Invoke，这方法不能重载，重载了就不知道哪些需要注入了
        /// </summary>
        /// <param name="context">必选参数，会注入进来</param>
        /// <param name="repository">注入进来的参数，不推荐，应该通过构造函数注入，这里仅测试用</param>
        /// <returns></returns>
        public Task Invoke(HttpContext context,IStringRepository repository)
        {
            if (_stringRepository != null)
            {
                _identity = _stringRepository.ToUpper(_identity);
                _useFor = _stringRepository.ToUpper(_useFor);
            }
            if (_stringRepository == null)
            {
                _stringRepository = repository;
                _identity = _stringRepository.ToUpper(_identity);
                _useFor = _stringRepository.ToUpper(_useFor);
            }

            context.Response.Headers["IceDog-Identity"] = _identity;
            context.Response.Headers["IceDog-Use-For"] =  _useFor;
            // Call the next delegate/middleware in the pipeline
            return _next(context);
        }
    }
}
